"""
基础工具，所有工具的抽象基类
这个架构确保了所有工具都有统一的接口，方便智能体调用和管理。
"""

from abc import ABC, abstractmethod
from typing import Any, Dict, Optional

# BaseModel 是来自 pydantic 库的一个核心类，主要用于数据验证和设置管理。
from pydantic import BaseModel, Field


class BaseTool(ABC, BaseModel):
    name: str
    description: str
    parameters: Optional[dict] = None

    # 这是 pydantic V1 的配置语法
    # pydantic 使用元类在类创建时扫描内部的 Config 类，元类会提取 Config 类中定义的配置选项，并应用到模型行为中
    # pydantic 默认只允许使用标准的 JSON 类型（str, int, float, bool, list, dict 等）
    # 当需要使用自定义类实例或其他复杂类型时，需要设置 arbitrary_types_allowed = True
    class Config:
        arbitrary_types_allowed = True

    # 前后双下划线的方法是 Python 的特殊方法（魔术方法），用于实现类的内置行为
    # __call__ 实例被被调用时执行
    # 为什么为 execute 封装一层 call：一种重要的设计模式，提供了统一的接口、额外的控制层和更好的可用性。
    async def __call__(self, **kwargs) -> Any:
        """Execute the tool with given parameters."""
        return await self.execute(**kwargs)

    @abstractmethod
    async def execute(self, **kwargs) -> Any:
        """Execute the tool with given parameters."""

    def to_param(self) -> Dict:
        """Convert tool to function call format."""
        return {
            "type": "function",
            "function": {
                "name": self.name,
                "description": self.description,
                "parameters": self.parameters,
            },
        }


class ToolResult(BaseModel):
    """Represents the result of a tool execution."""

    output: Any = Field(default=None)
    error: Optional[str] = Field(default=None)
    base64_image: Optional[str] = Field(default=None)
    system: Optional[str] = Field(default=None)

    class Config:
        arbitrary_types_allowed = True

    # 定义对象的布尔值表现：简洁地判断工具执行是否产生了有意义的结果。
    def __bool__(self):
        return any(getattr(self, field) for field in self.__fields__)

    # 定义加法操作的行为
    def __add__(self, other: "ToolResult"):
        def combine_fields(
                field: Optional[str], other_field: Optional[str], concatenate: bool = True
        ):
            if field and other_field:
                if concatenate:
                    return field + other_field
                raise ValueError("Cannot combine tool results")
            return field or other_field

        return ToolResult(
            output=combine_fields(self.output, other.output),
            error=combine_fields(self.error, other.error),
            base64_image=combine_fields(self.base64_image, other.base64_image, False),
            system=combine_fields(self.system, other.system),
        )

    # 定义对象被转换为字符串时的行为。
    def __str__(self):
        return f"Error: {self.error}" if self.error else self.output

    def replace(self, **kwargs):
        """Returns a new ToolResult with the given fields replaced."""
        # return self.copy(update=kwargs)
        return type(self)(**{**self.dict(), **kwargs})


class CLIResult(ToolResult):
    """A ToolResult that can be rendered as a CLI output."""


class ToolFailure(ToolResult):
    """A ToolResult that represents a failure."""
